Chapter 2: Diffraction


5.5. Homework 4#

Analyzing Spot Diffraction Pattern

Download

part of

MSE672: Introduction to Transmission Electron Microscopy

by Gerd Duscher, Spring 2023

Microscopy Facilities
Institute of Advanced Materials & Manufacturing
Materials Science & Engineering
The University of Tennessee, Knoxville

Background and methods to analysis and quantification of data acquired with transmission electron microscopes.

5.5.1. Overview#

This homework follows the notebook: Analyzing Spot Diffraction Pattern

5.5.2. Load relevant python packages#

5.5.2.1. Check Installed Packages#

import sys
from pkg_resources import get_distribution, DistributionNotFound

def test_package(package_name):
    """Test if package exists and returns version or -1"""
    try:
        version = get_distribution(package_name).version
    except (DistributionNotFound, ImportError) as err:
        version = '-1'
    return version

if test_package('pyTEMlib') < '0.2022.2.3':
    print('installing pyTEMlib')
    !{sys.executable} -m pip install  --upgrade pyTEMlib
print('done')
done

5.5.2.2. Load the plotting and figure packages#

Import the python packages that we will use:

Beside the basic numerical (numpy) and plotting (pylab of matplotlib) libraries,

  • three dimensional plotting and some libraries from the book

  • kinematic scattering library.

%pylab  notebook
%gui qt
    
# 3D and selection plotting package 
from mpl_toolkits.mplot3d import Axes3D # 3D plotting
from matplotlib.widgets import  EllipseSelector


# additional package 
import itertools 
import scipy.constants as const
import os
# our blob detectors from the scipy image package
from skimage.feature import blob_dog

# Import libraries from the book
import pyTEMlib
import pyTEMlib.kinematic_scattering as ks         # Kinematic sCattering Library
                             # with Atomic form factors from Kirklands book
import pyTEMlib.file_tools as ft     

# it is a good idea to show the version numbers at this point for archiving reasons.
__notebook_version__ = '2022.02.18'
print('pyTEM version: ', pyTEMlib.__version__)
print('notebook version: ', __notebook_version__)
Populating the interactive namespace from numpy and matplotlib
Symmetry functions of spglib enabled
Using kinematic_scattering library version {_version_ }  by G.Duscher
pyTEM version:  0.2022.2.1
notebook version:  2022.02.10

5.5.3. Load Ring-Diffraction Pattern#

This ho

5.5.3.1. First we select the diffraction pattern#

In the second lab we used a sample of either gold (Tuesday) or Aluminium (Wednesday)

Download your images from the google drive at https://drive.google.com/drive/folders/1TId7PiGUbip8m8JgX2FL5PaNjld1idzt?usp=sharing

You must log into Google with your UTK account to be able to read these data.

Go to the folder of you data and select one
The dynamic range of diffraction patterns is too high for computer screens and so we take the logarithm of the intensity.

# ------Input -------------
load_your_own_data = False
# -------------------------

try:
    # close any open files before open new one
    main_dataset.h5_dataset.file.close()
except:
    pass
if load_your_own_data:
    main_dataset = ft.open_file()
else:  # load example
    main_dataset = ft.open_file(os.path.join("../example_data", "Si001_300mm_alpha0.1_beta9.4_diff.dm3"))
view = main_dataset.plot(vmax=20000)
Cannot overwrite file. Using:  Si001_300mm_alpha0.1_beta9.4_diff-3.hf5
C:\Users\gduscher\Anaconda3\lib\site-packages\pyNSID\io\hdf_utils.py:350: FutureWarning: validate_h5_dimension may be removed in a future version
  warn('validate_h5_dimension may be removed in a future version',

5.5.4. Finding the center#

5.5.4.1. Select the center yourself#

Select the center of the screen with the ellipse selection tool

## Access the data of the loaded image
radius = 559 
diff_pattern = np.array(main_dataset.T)
diff_pattern = diff_pattern-diff_pattern.min()

center = np.array([1024, 1024])

plt.figure(figsize=(8, 6))
plt.imshow(np.log(3.+diff_pattern), origin = 'upper')
current_axis = plt.gca()
selector = EllipseSelector(current_axis, None,interactive=True , drawtype='box')  # gca get current axis (plot)

selector.to_draw.set_visible(True)
center = np.array(center)

selector.extents = (center[0]-radius,center[0]+radius,center[1]-radius,center[1]+radius)

Get center coordinates from selection

xmin, xmax, ymin, ymax = selector.extents
x_center, y_center = selector.center
x_shift = x_center - diff_pattern.shape[0]/2
y_shift = y_center - diff_pattern.shape[1]/2
print(f'radius = {(xmax-xmin)/2:.0f} pixels')

center = (x_center, y_center )
print(f'center = {center} [pixels]')

out_tags ={}
out_tags['center'] = center
radius = 559 pixels
center = (1112.6580086580084, 1055.030303030303) [pixels]

5.5.5. Determine Bragg Peaks#

Peak finding is actually not as simple as it looks

# The beam stop is rather dark
beam_stop = np.argwhere(diff_pattern.T < 100)

# Determine all spots

dif = np.log2(1+diff_pattern)
dif = dif-dif.min() # blog detector does not like negative values
spots = blob_dog(dif.T, max_sigma=12, threshold=.9)

Bragg_spots = []
# We only consider spots not associated with the beam stop (which confuses the blob finder)
for spot in spots:
    if np.min(np.linalg.norm(beam_stop-spot[:2], axis=1))> 100:
        Bragg_spots.append(spot[0:2])
Bragg_spots = np.array(Bragg_spots)
Bragg_spots = Bragg_spots[np.argsort(np.linalg.norm(Bragg_spots[:,:2]-center, axis=1)),:]

plt.figure()
plt.imshow(np.log2(1+diff_pattern),cmap="gray", vmin=np.max(np.log2(1+diff_pattern))*0.5)

plt.scatter(Bragg_spots[:,0], Bragg_spots[:,1], c='green',  alpha = 0.5)
<matplotlib.collections.PathCollection at 0x1e702f65550>

5.5.5.1. Refine Center#

We use the N innermost reflections and the average of those positions is the new center

Please choose the max_distance value so that you have a symmetric selection of Bragg spots around the center

# ----- Input -------------
max_distance = 600 # pixel
# -------------------------

close_spots = Bragg_spots[np.linalg.norm(Bragg_spots[:,:2]-center[:2], axis=1) <max_distance]

refined_center = np.average(close_spots, axis=0)
close_spots -= refined_center

spots_experiment = (Bragg_spots-refined_center)

fig = plt.figure()
extent= np.array([-refined_center[0], diff_pattern.shape[0]-refined_center[0],
                  diff_pattern.shape[1]-refined_center[1], -refined_center[1]])
plt.imshow(np.log2(1+diff_pattern), cmap="gray", extent=extent, vmin=np.max(np.log2(1 + diff_pattern)) * 0.5)

plt.scatter(spots_experiment[:,0], spots_experiment[:,1], c='green',  alpha = 0.5,
           label='spots')
plt.scatter(close_spots[:,0], close_spots[:,1], c='orange',  alpha = 0.5,
           label='close spots')

plt.xlabel('reciprocal distance [1/$\AA$]')
plt.scatter(0, 0, color='red')
<matplotlib.collections.PathCollection at 0x1e702fe59a0>

5.5.6. Calculate Spot Pattern#

see Plotting of Diffraction Pattern for details

# -------Input  -----
material = 'silicon'
zone_hkl = [0,0,1]
# -------------------

atoms  = ks.structure_by_name(material)
atoms.info['experimental']={}
### Define experimental parameters:
atoms.info['experimental']['acceleration_voltage_V'] = 200.0 *1000.0 #V
atoms.info['experimental']['new_figure'] = False
atoms.info['experimental']['plot FOV'] = 3  # in 1/Ang
atoms.info['experimental']['convergence_angle_mrad'] = 0
atoms.info['experimental']['zone_hkl'] = np.array(zone_hkl)  # incident nearest zone axis: defines Laue Zones!!!!
atoms.info['experimental']['mistilt']  = np.array([0,0,0])  # mistilt in degrees
atoms.info['experimental']['Sg_max'] = .04 # 1/Ang  maximum allowed excitation error ; This parameter is related to the thickness
atoms.info['experimental']['hkl_max'] = 15   # Highest evaluated Miller indices

######################################
# Diffraction Simulation of Crystal #
######################################

d = ks.kinematic_scattering(atoms, verbose = True)
reciprocal_unit_cell
[[0.184 0.    0.   ]
 [0.    0.184 0.   ]
 [0.    0.    0.184]]
The inner potential is 46.5V
Using an acceleration voltage of 200.0kV
Magnitude of incident wave vector in material: 40.5 1/Ang and in vacuum: 39.9 1/Ang
Which is an wave length of 2.472 pm in the material and 2.508 pm in the vacuum
The convergence angle of 0.0mrad = 0.00 1/A
Magnitude of incident wave vector in material: 40.5 1/A which is a wavelength 2.472 pm
Rotation alpha 0.0 degree,  beta 0.0 degree
from zone axis [0 0 1]
Tilting 1 by 0.00  in alpha and 0.00 in beta direction results in :
Next nearest zone axes are:
Center of Ewald sphere  [ 0.          0.         40.45252569]
Of the 29790 tested reciprocal_unit_cell points, 340 have an excitation error less than 0.04 1/Angstrom
Of the 340 possible reflection 56 are allowed.
Laue_circle [0. 0. 0.]
 There are 36 allowed reflections in the zero order Laue Zone
 There are 20 allowed reflections in the first order Laue Zone
 There are 0 allowed reflections in the second order Laue Zone
 There are 0 allowed reflections in the higher order Laue Zone
 hkl  	 Laue zone 	 Intensity (*1 and 	 log) 	 length 

 [-15. -15.   1.] 	 [-2.76198332 -2.76198332  0.18413222] 	 0.101 	  0.097 	  3.910   
 [-15. -13.   1.] 	 [-2.76198332 -2.39371888  0.18413222] 	 0.131 	  0.123 	  3.660   
 [-15. -11.   1.] 	 [-2.76198332 -2.02545444  0.18413222] 	 0.168 	  0.155 	  3.430   
 [-15.  11.   1.] 	 [-2.76198332  2.02545444  0.18413222] 	 0.168 	  0.155 	  3.430   
 [-15.  13.   1.] 	 [-2.76198332  2.39371888  0.18413222] 	 0.131 	  0.123 	  3.660   
 [-15.  15.   1.] 	 [-2.76198332  2.76198332  0.18413222] 	 0.101 	  0.097 	  3.910   
 [-13. -15.   1.] 	 [-2.39371888 -2.76198332  0.18413222] 	 0.131 	  0.123 	  3.660   
 [-13.  15.   1.] 	 [-2.39371888  2.76198332  0.18413222] 	 0.131 	  0.123 	  3.660   
 [-11. -15.   1.] 	 [-2.02545444 -2.76198332  0.18413222] 	 0.168 	  0.155 	  3.430   
 [-11.  15.   1.] 	 [-2.02545444  2.76198332  0.18413222] 	 0.168 	  0.155 	  3.430   
 [-8. -4.  0.] 	 [-1.47305777 -0.73652889  0.        ] 	 8.632 	  2.265 	  1.647   
 [-8.  0.  0.] 	 [-1.47305777  0.          0.        ] 	 12.008 	  2.566 	  1.473   
 [-8.  4.  0.] 	 [-1.47305777  0.73652889  0.        ] 	 8.632 	  2.265 	  1.647   
 [-6. -6.  0.] 	 [-1.10479333 -1.10479333  0.        ] 	 10.107 	  2.408 	  1.562   
 [-6. -2.  0.] 	 [-1.10479333 -0.36826444  0.        ] 	 23.163 	  3.185 	  1.165   
 [-6.  2.  0.] 	 [-1.10479333  0.36826444  0.        ] 	 23.163 	  3.185 	  1.165   
 [-6.  6.  0.] 	 [-1.10479333  1.10479333  0.        ] 	 10.107 	  2.408 	  1.562   
 [-4. -8.  0.] 	 [-0.73652889 -1.47305777  0.        ] 	 8.632 	  2.265 	  1.647   
 [-4. -4.  0.] 	 [-0.73652889 -0.73652889  0.        ] 	 31.489 	  3.481 	  1.042   
 [-4.  0.  0.] 	 [-0.73652889  0.          0.        ] 	 84.041 	  4.443 	  0.737   
 [-4.  4.  0.] 	 [-0.73652889  0.73652889  0.        ] 	 31.489 	  3.481 	  1.042   
 [-4.  8.  0.] 	 [-0.73652889  1.47305777  0.        ] 	 8.632 	  2.265 	  1.647   
 [-2. -6.  0.] 	 [-0.36826444 -1.10479333  0.        ] 	 23.163 	  3.185 	  1.165   
 [-2. -2.  0.] 	 [-0.36826444 -0.36826444  0.        ] 	 221.914 	  5.407 	  0.521   
 [-2.  2.  0.] 	 [-0.36826444  0.36826444  0.        ] 	 221.914 	  5.407 	  0.521   
 [-2.  6.  0.] 	 [-0.36826444  1.10479333  0.        ] 	 23.163 	  3.185 	  1.165   
 [ 0. -8.  0.] 	 [ 0.         -1.47305777  0.        ] 	 12.008 	  2.566 	  1.473   
 [ 0. -4.  0.] 	 [ 0.         -0.73652889  0.        ] 	 84.041 	  4.443 	  0.737   
 [0. 4. 0.] 	 [0.         0.73652889 0.        ] 	 84.041 	  4.443 	  0.737   
 [0. 8. 0.] 	 [0.         1.47305777 0.        ] 	 12.008 	  2.566 	  1.473   
 [ 2. -6.  0.] 	 [ 0.36826444 -1.10479333  0.        ] 	 23.163 	  3.185 	  1.165   
 [ 2. -2.  0.] 	 [ 0.36826444 -0.36826444  0.        ] 	 221.914 	  5.407 	  0.521   
 [2. 2. 0.] 	 [0.36826444 0.36826444 0.        ] 	 221.914 	  5.407 	  0.521   
 [2. 6. 0.] 	 [0.36826444 1.10479333 0.        ] 	 23.163 	  3.185 	  1.165   
 [ 4. -8.  0.] 	 [ 0.73652889 -1.47305777  0.        ] 	 8.632 	  2.265 	  1.647   
 [ 4. -4.  0.] 	 [ 0.73652889 -0.73652889  0.        ] 	 31.489 	  3.481 	  1.042   
 [4. 0. 0.] 	 [0.73652889 0.         0.        ] 	 84.041 	  4.443 	  0.737   
 [4. 4. 0.] 	 [0.73652889 0.73652889 0.        ] 	 31.489 	  3.481 	  1.042   
 [4. 8. 0.] 	 [0.73652889 1.47305777 0.        ] 	 8.632 	  2.265 	  1.647   
 [ 6. -6.  0.] 	 [ 1.10479333 -1.10479333  0.        ] 	 10.107 	  2.408 	  1.562   
 [ 6. -2.  0.] 	 [ 1.10479333 -0.36826444  0.        ] 	 23.163 	  3.185 	  1.165   
 [6. 2. 0.] 	 [1.10479333 0.36826444 0.        ] 	 23.163 	  3.185 	  1.165   
 [6. 6. 0.] 	 [1.10479333 1.10479333 0.        ] 	 10.107 	  2.408 	  1.562   
 [ 8. -4.  0.] 	 [ 1.47305777 -0.73652889  0.        ] 	 8.632 	  2.265 	  1.647   
 [8. 0. 0.] 	 [1.47305777 0.         0.        ] 	 12.008 	  2.566 	  1.473   
 [8. 4. 0.] 	 [1.47305777 0.73652889 0.        ] 	 8.632 	  2.265 	  1.647   
 [ 11. -15.   1.] 	 [ 2.02545444 -2.76198332  0.18413222] 	 0.168 	  0.155 	  3.430   
 [11. 15.  1.] 	 [2.02545444 2.76198332 0.18413222] 	 0.168 	  0.155 	  3.430   
 [ 13. -15.   1.] 	 [ 2.39371888 -2.76198332  0.18413222] 	 0.131 	  0.123 	  3.660   
 [13. 15.  1.] 	 [2.39371888 2.76198332 0.18413222] 	 0.131 	  0.123 	  3.660   
 [ 15. -15.   1.] 	 [ 2.76198332 -2.76198332  0.18413222] 	 0.101 	  0.097 	  3.910   
 [ 15. -13.   1.] 	 [ 2.76198332 -2.39371888  0.18413222] 	 0.131 	  0.123 	  3.660   
 [ 15. -11.   1.] 	 [ 2.76198332 -2.02545444  0.18413222] 	 0.168 	  0.155 	  3.430   
 [15. 11.  1.] 	 [2.76198332 2.02545444 0.18413222] 	 0.168 	  0.155 	  3.430   
 [15. 13.  1.] 	 [2.76198332 2.39371888 0.18413222] 	 0.131 	  0.123 	  3.660   
 [15. 15.  1.] 	 [2.76198332 2.76198332 0.18413222] 	 0.101 	  0.097 	  3.910   
Calculating Kikuchi lines for zone:  [0. 0. 1.]
done

5.5.7. Comparison#

Comparison between experimental pattern and kinematic theory

Experimental Bragg reflection in polar coordinates

print('distance [pixel]   angle [degree] ')
for spot in close_spots:
    
    print(f'{np.linalg.norm(spot):8.3f} \t {np.degrees(np.arctan2(spot[0], spot[1])):5.1f}  ' )
distance [pixel]   angle [degree] 
 336.784 	  75.3  
 336.300 	 -104.7  
 360.840 	 165.6  
 360.716 	 -14.3  
 492.756 	 122.5  
 496.333 	 -151.6  
 496.095 	  28.4  
 493.178 	 -57.6  

Select the largest g distance that you want to have indexed.

# ----- Input ------
max_g_length = 1.
# ------------------
allowed_g = atoms.info['diffraction']['allowed']['g']
allowed_hkl = atoms.info['diffraction']['allowed']['hkl']

close = np.where(np.linalg.norm(allowed_g[:, :2], axis=1)<max_g_length)
smallest_reciprocal_length = np.min(np.linalg.norm(allowed_g[:, :2], axis=1))

print(f' Smallest reciprocal length is {smallest_reciprocal_length:.3f} 1/Ang')
print()
                    
                                    
print('  hkl          coordinates             lengths in 1/Ang\n')
for index in close[0]:
    print(allowed_hkl[index], '\t', np.round(allowed_g[index], 3), '\t',
          np.linalg.norm(allowed_g[index]))
print(smallest_reciprocal_length )
 Smallest reciprocal length is 0.521 1/Ang

  hkl          coordinates             lengths in 1/Ang

[-4.  0.  0.] 	 [-0.737  0.     0.   ] 	 0.7365288866629349
[-2. -2.  0.] 	 [-0.368 -0.368  0.   ] 	 0.5208045702991394
[-2.  2.  0.] 	 [-0.368  0.368  0.   ] 	 0.5208045702991394
[ 0. -4.  0.] 	 [ 0.    -0.737  0.   ] 	 0.7365288866629349
[0. 4. 0.] 	 [0.    0.737 0.   ] 	 0.7365288866629349
[ 2. -2.  0.] 	 [ 0.368 -0.368  0.   ] 	 0.5208045702991394
[2. 2. 0.] 	 [0.368 0.368 0.   ] 	 0.5208045702991394
[4. 0. 0.] 	 [0.737 0.    0.   ] 	 0.7365288866629349
0.5208045702991394

Enter the distance from center for one of the closest experimental Bragg reflections in pixel with assoicated angle

# -------Input of grain size ----
first_peak_length_in_pixel = 336.78377
rotation_angle = 75.29323
# degrees
# -------------------------------

first_peak_reciprocal_distance =  np.min(np.linalg.norm(allowed_g[:,:2], axis=1))
pixel_size = first_peak_reciprocal_distance/first_peak_length_in_pixel
closest_sim = np.argmin(np.linalg.norm(allowed_g[:,:2], axis=1))

angle_closest_reflection = np.degrees(np.arctan2(allowed_g[closest_sim,1], allowed_g[closest_sim,0]))

rotation_angle = rotation_angle - angle_closest_reflection
tags_simulation = atoms.info['diffraction']

scaled_extent= extent*pixel_size

angle = np.radians(rotation_angle)
c = np.cos(angle)
s = np.sin(angle)
r_mat = np.array([[c,-s,0],[s,c,0],[0,0,1]])
rmat_g= r_mat

spots_experiment_scaled = spots_experiment*pixel_size

spots_simulation =  np.dot(allowed_g, r_mat)
spots_ZOLZ = spots_simulation[atoms.info['diffraction']['allowed']['ZOLZ']]

fig = plt.figure()
fig.suptitle(material+' SAED in ' + str( atoms.info['experimental']['zone_hkl']), fontsize=20) 
plt.scatter(spots_experiment_scaled[:,0], spots_experiment_scaled[:,1], c='blue',  alpha = 0.5, label='experiment')
plt.scatter(spots_simulation[:,0], spots_simulation[:,1], c='red',  alpha = 0.2,   label='simulation')
plt.imshow(np.log2(1+diff_pattern), cmap="gray", extent=scaled_extent, vmin=np.max(np.log2(1 + diff_pattern)) * 0.5)
for i in range(len(spots_simulation)):
    if np.linalg.norm(spots_simulation[i]) < max_g_length:
        plt.text(spots_simulation[i,0], spots_simulation[i,1],str(tags_simulation['allowed']['hkl'][i]),
                fontsize = 8, horizontalalignment = 'center', verticalalignment ='bottom')
plt.legend()
[-4.  0.  0.]
[-2. -2.  0.]
[-2.  2.  0.]
[ 0. -4.  0.]
[0. 4. 0.]
[ 2. -2.  0.]
[2. 2. 0.]
[4. 0. 0.]
<matplotlib.legend.Legend at 0x1e700bfd730>

5.5.8. Homework#

Index the diffraction pattern for two different zone axes.

Submit two notebooks each with a diffraction pattern of a different zone axis

Optional:

Plot the indicated camera length over the pixel size!

for i in range(len(spots_simulation)):
    if np.linalg.norm(spots_simulation[1]) <1:
        print(tags_simulation['allowed']['hkl'][i])